package com.kmxd.ams.core.util;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import com.google.common.collect.Maps;
import com.itextpdf.text.Element;
import com.itextpdf.text.Image;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.*;
import lombok.extern.slf4j.Slf4j;

import javax.swing.*;
import java.awt.*;
import java.io.FileOutputStream;
import java.util.Date;
import java.util.Map;

/**
 * 水印工具
 *
 * @author nickbi
 */
@Slf4j
public class WatermarkUtil {

  private static final int INTERVAL = -5;

  /**
   * 添加图片水印
   *
   * @param srcFile 文件
   * @param destFile 存储路径
   * @param text 文本内容
   * @param opacity 透明度
   * @param angle 倾斜度
   * @param fontsize 字体大小
   */
  public static void addPdfWatermark(
          String srcFile, String destFile, String text, double opacity, double angle, int fontsize) {

    try {
      PdfReader reader = new PdfReader(srcFile);
      PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(destFile));
      byte[] ownerPassword = "000000".getBytes();
      stamper.setEncryption(null, ownerPassword, PdfWriter.ALLOW_ASSEMBLY, false);
      stamper.setEncryption(null, ownerPassword, PdfWriter.ALLOW_COPY, false);
      stamper.setEncryption(null, ownerPassword, PdfWriter.ALLOW_DEGRADED_PRINTING, false);
      stamper.setEncryption(null, ownerPassword, PdfWriter.ALLOW_FILL_IN, false);
      stamper.setEncryption(null, ownerPassword, PdfWriter.ALLOW_MODIFY_ANNOTATIONS, false);
      stamper.setEncryption(null, ownerPassword, PdfWriter.ALLOW_MODIFY_CONTENTS, false);
      stamper.setEncryption(null, ownerPassword, PdfWriter.ALLOW_PRINTING, false);
      stamper.setEncryption(null, ownerPassword, PdfWriter.ALLOW_SCREENREADERS, false);
      stamper.setEncryption(null, ownerPassword, PdfWriter.DO_NOT_ENCRYPT_METADATA, true);
      stamper.setViewerPreferences(PdfWriter.HideToolbar | PdfWriter.HideMenubar);
      // CARRER
      BaseFont base = BaseFont.createFont(findFonts(), BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
      Rectangle pageRect = null;
      PdfGState gs = new PdfGState();
      double divide = NumberUtil.div(opacity, 255d, 2);
      gs.setFillOpacity((float) divide);
      gs.setStrokeOpacity((float) divide);
      int total = reader.getNumberOfPages() + 1;
      JLabel label = new JLabel();
      FontMetrics metrics;
      int textH = 0;
      int textw = 0;
      label.setText(text);
      metrics = label.getFontMetrics(label.getFont());
      textH = metrics.getHeight();
      textw = metrics.stringWidth(label.getText());
      PdfContentByte under;
      for (int i = 1; i < total; i++) {
        pageRect = reader.getPageSizeWithRotation(i);
        //        float x = pageRect.getWidth() / 2;
        //        float y = pageRect.getHeight() / 2;
        under = stamper.getOverContent(i);
        under.saveState();
        under.setGState(gs);
        under.beginText();
        under.setFontAndSize(base, fontsize);
        for (int height = INTERVAL + textH;
             height < pageRect.getHeight();
             height = height + textH * 8) {
          for (int width = INTERVAL + textw;
               width < pageRect.getWidth() + textw;
               width = width + textw) {
            under.showTextAligned(
                    Element.ALIGN_LEFT, text, width - textw, height - textH, (float) angle);
          }
        }
        // 添加水印文字
        under.endText();
      }
      stamper.close();
      reader.close();
    } catch (Exception e) {
      log.error(e.getMessage(), e);
    }
  }

  /**
   * 添加图片水印
   *
   * @param srcFile 文件
   * @param destFile 存储路径
   * @param text 文本内容
   * @param opacity 透明度
   * @param angle 倾斜度
   * @param fontsize 字体大小
   * @param imageFile 水印图片
   * @param x 图片坐标x
   * @param y 图片坐标y
   * @param imageAngle 图片倾斜度
   */
  public static void addPdfWatermark(
          String srcFile,
          String destFile,
          String text,
          double opacity,
          double angle,
          int fontsize,
          String imageFile,
          int x,
          int y,
          double imageAngle) {

    try {
      PdfReader reader = new PdfReader(srcFile);
      PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(destFile));
      byte[] ownerPassword = "000000".getBytes();
      stamper.setEncryption(null, ownerPassword, PdfWriter.ALLOW_ASSEMBLY, false);
      stamper.setEncryption(null, ownerPassword, PdfWriter.ALLOW_COPY, false);
      stamper.setEncryption(null, ownerPassword, PdfWriter.ALLOW_DEGRADED_PRINTING, false);
      stamper.setEncryption(null, ownerPassword, PdfWriter.ALLOW_FILL_IN, false);
      stamper.setEncryption(null, ownerPassword, PdfWriter.ALLOW_MODIFY_ANNOTATIONS, false);
      stamper.setEncryption(null, ownerPassword, PdfWriter.ALLOW_MODIFY_CONTENTS, false);
      stamper.setEncryption(null, ownerPassword, PdfWriter.ALLOW_PRINTING, false);
      stamper.setEncryption(null, ownerPassword, PdfWriter.ALLOW_SCREENREADERS, false);
      stamper.setEncryption(null, ownerPassword, PdfWriter.DO_NOT_ENCRYPT_METADATA, true);
      stamper.setViewerPreferences(PdfWriter.HideToolbar | PdfWriter.HideMenubar);
      BaseFont base = BaseFont.createFont(findFonts(), BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
      Rectangle pageRect = null;
      PdfGState gs = new PdfGState();
      double divide = NumberUtil.div(opacity, 255d, 2);
      // 透明度
      gs.setFillOpacity((float) divide);
      gs.setStrokeOpacity((float) divide);
      int total = reader.getNumberOfPages() + 1;
      JLabel label = new JLabel();
      FontMetrics metrics;
      int textH = 0;
      int textw = 0;
      if (StrUtil.isNotBlank(text)) {
        label.setText(text);
        metrics = label.getFontMetrics(label.getFont());
        // 字符串的高，只和字体有关
        textH = metrics.getHeight();
        textw = metrics.stringWidth(label.getText());
      }
      // 图片水印
      Image image = Image.getInstance(imageFile);
      image.setAbsolutePosition(x, y);
      image.setAlignment(Element.ALIGN_CENTER);
      // 倾斜度
      image.setRotationDegrees((float) imageAngle);
      PdfContentByte under;
      for (int i = 1; i < total; i++) {
        pageRect = reader.getPageSizeWithRotation(i);
        under = stamper.getOverContent(i);
        under.addImage(image);
        under.saveState();
        under.setGState(gs);

        if (StrUtil.isNotBlank(text)) {
          under.beginText();
          under.setFontAndSize(base, fontsize);
          for (int height = INTERVAL + textH;
               height < pageRect.getHeight();
               height = height + textH * 8) {
            for (int width = INTERVAL + textw;
                 width < pageRect.getWidth() + textw;
                 width = width + textw) {
              under.showTextAligned(
                      Element.ALIGN_LEFT, text, width - textw, height - textH, (float) angle);
            }
          }
          // 添加水印文字
          under.endText();
        }
      }
      stamper.close();
      reader.close();
    } catch (Exception e) {
      log.error(e.getMessage(), e);
    }
  }

  /**
   * 动态水印格式化
   *
   * @param text 动态水印内容
   * @return
   */
  public static String format(String text) {
    Map<String, Object> map = getDefaultInfo();
    return StrUtil.format(text, map);
  }

  public static String findFonts() {
    return "fonts/simfang.ttf";
  }

  /**
   * 动态水印格式化
   *
   * @param source 数据信息
   * @param text 动态水印格式
   * @return 格式化字符串
   */
  public static String format(Object source, String text) {
    Map<String, Object> map = BeanUtil.beanToMap(source);
    map.putAll(getDefaultInfo());
    return StrUtil.format(text, map);
  }

  /**
   * 默认动态信息
   *
   * @return map
   */
  public static Map<String, Object> getDefaultInfo() {
    Map<String, Object> map = Maps.newHashMap();
    map.put("year", DateUtil.year(new Date()));
    map.put("deptName", SecurityUtil.getLoginUser().getDeptName());
    map.put("deptId", SecurityUtil.getLoginUser().getDeptId());
    map.put("userId", SecurityUtil.getUserId());
    map.put("username", SecurityUtil.getUsername());
    map.put("realname", SecurityUtil.getRealname());
    map.put("date", DateUtil.format(new Date(), DatePattern.NORM_DATE_PATTERN));
    return map;
  }
}
